package configx

import (
	"io/fs"
	"os"
	"path"
	"path/filepath"
	"strings"

	jsoniter "github.com/json-iterator/go"

	"github.com/spf13/viper"
)

// UnmarshalFiles 解析配置文件
func UnmarshalFiles(cfgPath string, config any) (*viper.Viper, error) {
	const PathSeparator = string(os.PathSeparator)
	if !strings.HasSuffix(cfgPath, PathSeparator) {
		cfgPath += PathSeparator
	}

	// 实例化viper
	cfg := viper.New()

	// 读取application.yaml
	cfg.AddConfigPath(path.Dir(cfgPath))
	cfg.SetConfigName("application")
	if err := cfg.ReadInConfig(); err != nil {
		return nil, err
	}

	// 读取其他文件
	cfgFiles := make([]string, 0)
	filepath.Walk(cfgPath, func(filePath string, info fs.FileInfo, err error) error {
		if !info.IsDir() && strings.ToLower(path.Ext(info.Name())) == ".yaml" && info.Name() != "application.yaml" {
			cfgFiles = append(cfgFiles, info.Name())
		}
		return err
	})

	// 循环读取配置文件
	for _, cfgFile := range cfgFiles {
		cfg.AddConfigPath(cfgPath)
		cfg.SetConfigName(strings.Split(cfgFile, ".")[0])
		if err := cfg.MergeInConfig(); err != nil {
			return nil, err
		}
	}

	// 解析文件到map
	var cfgMap map[string]any
	if err := cfg.Unmarshal(&cfgMap); err != nil {
		return nil, err
	}

	// map转对象
	json := jsoniter.Config{
		EscapeHTML:             true,
		SortMapKeys:            true,
		ValidateJsonRawMessage: true,
		TagKey:                 "mapstructure",
	}.Froze()
	if cBytes, err := json.Marshal(cfgMap); err != nil {
		return nil, err
	} else if err = json.Unmarshal(cBytes, config); err != nil {
		return nil, err
	}

	return cfg, nil
}
